package com.lebang.service;

import com.alibaba.fastjson.JSON;
import com.lebang.component.RedisClient;
import com.lebang.component.RedisSdkClient;
import com.lebang.component.UMengPushComponent;
import com.lebang.domain.*;
import com.lebang.entity.RequestHeaders;
import com.lebang.entity.member.LbbMember;
import com.lebang.example.*;
import com.lebang.mapper.*;
import com.lebang.model.MoneyCategory;
import com.lebang.model.Whether;
import com.lebang.model.enums.buss.*;
import com.lebang.service.buss.MemberTradeService;
import com.lebang.service.sys.DictService;
import com.lebangweb.common.TextUtil;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.lebang.service.CpaService.ZY_DATA;

/**
 * @Author: hwq
 * @Date: 2019/12/23 17:08
 * @Version 1.0
 */
@Service
public class DownAppService extends BaseService<DownloadPkgDetail, Long, DownloadPkgDetailExample> {
    @Autowired
    private RedisSdkClient redisSdkClient;
    @Autowired
    private DownloadPkgDetailMapper downloadPkgDetailMapper;
    @Autowired
    private DownloadMemberRecordMapper recordMapper;
    @Autowired
    private MemberTradeService tradeService;
    @Autowired
    private UMengPushComponent uMengPushComponent;
    @Autowired
    private MemberNoticeService noticeService;
    @Autowired
    private PointService pointService;
    @Autowired
    private TaskRouseMapper rouseMapper;
    @Autowired
    private LbbMemberMapper lbbMemberMapper;

    @Autowired
    private MemberClidkRouseRecordMapper clidkRouseRecordMapper;
    public static final String TASK_ROUSE_POOLS = "TASK_ROUSE_POOLS";
    @Autowired
    private MemberClickRouseMapper clickRouseMapper;

    @Autowired
    private PkgEarnInfoMapper pkgEarnInfoMapper;


    public static final String TASK_ROUSE_CLICK_CACHE = "TASK_ROUSE_CLICK_CACHE:";


    public String getClickCacheKey() {
        return TASK_ROUSE_CLICK_CACHE;
    }

    /**
     * 判断应用名称是否存在
     *
     * @param name
     * @return
     */
    public DownloadPkgDetail selectByAppName(String name) {
        DownloadPkgDetail vo = downloadPkgDetailMapper.selectByAppName(name);
        if (vo == null) {
            DownloadPkgDetail downloadPkgDetail = new DownloadPkgDetail();
            downloadPkgDetail.setCreateTime(LocalDateTime.now());
            downloadPkgDetail.setModifyTime(LocalDateTime.now());
            downloadPkgDetail.setHasDeleted(Whether.NO.getDbIndex());
            downloadPkgDetail.setPkgName("");
            downloadPkgDetail.setAppName(name);
            downloadPkgDetail.setOpenLock(0);
            downloadPkgDetailMapper.insertSelective(downloadPkgDetail);
        }
        return vo;
    }

    /**
     * 领取任务 -- 外部数据源
     *
     * @param memberId
     * @param type
     * @param header
     * @return
     */
    public DownloadMemberRecord pull(String memberId, Integer type, RequestHeaders header, TaskRouse rouse) {
        DownloadMemberRecord record = new DownloadMemberRecord();
        LocalDateTime time = lbbMemberMapper.selectCreaTimeByMemberId(memberId);
        if (time != null) {
            if (LocalDate.now().equals(time.toLocalDate())) {
                record.setIsNewMember(Whether.YES.getDbIndex());
            } else {
                record.setIsNewMember(Whether.NO.getDbIndex());
            }
        } else {
            record.setIsNewMember(-1);
        }
        record.setVersion(header.getVersion());
        record.setPkgName("");
        record.setAppName("");
        record.setMoney(0);
        record.setType(type);
        record.setRewardType(rouse.getRewardType());
        if (type > 0) {
            record.setTime(rouse.getRouseTime());
        } else {
            record.setTime(rouse.getLookTime());
        }
        record.setCreateTime(LocalDateTime.now());
        record.setHasDeleted(Whether.NO.getDbIndex());
        record.setCategory(null);
        record.setMemberId(memberId);
        record.setSdkKey(rouse.getSdkKey());
        record.setStatus(DownStatus.WAIT_PUSH.getIndex());
        record.setUa(header.getUa());
        record.setImei(header.getImei());
        record.setIpAddress(header.getIpAddr());
        record.setAppStore(header.getAppStore());
        recordMapper.insertSelective(record);
        return record;
    }


    /**
     * 取一个随机的数据源
     *
     * @param appStore
     * @param version
     * @return
     */
    public TaskRouse getRandomAllKey(String appStore, int version, String memberId) {
        List<String> filterSdkKey=this.filterSdkKey(memberId);
        filterSdkKey.add("ABCD8888");
        TaskRouseExample example = new TaskRouseExample();
        example.createCriteria()
                .andBrandNotLike("%" + appStore + "%")
                .andEnableEqualTo(1)
                .andVersionLessThanOrEqualTo(version)
        .andSdkKeyNotIn(filterSdkKey);
        return randomByWeight(rouseMapper.selectByExample(example));
    }
    /**
     * 取一个随机的数据源不包括自营
     *
     * @param appStore
     * @param version
     * @return
     */
    public TaskRouse getRandomAllKeyNotZy(String appStore, int version, String memberId) {
        List<String> filterSdkKey=this.filterSdkKey(memberId);
        filterSdkKey.add(ZY_DATA);
        TaskRouseExample example = new TaskRouseExample();
        example.createCriteria()
                .andBrandNotLike("%" + appStore + "%")
                .andEnableEqualTo(1)
                .andVersionLessThanOrEqualTo(version)
                .andSdkKeyNotIn(filterSdkKey);
        return randomByWeight(rouseMapper.selectByExample(example));
    }


    /**
     * 根据权重随机一个
     *
     * @param rouses
     * @return
     */
    public TaskRouse randomByWeight(List<TaskRouse> rouses) {
        if(rouses.size()==0){
            return null;
        }
        Collections.shuffle(rouses);
        Integer maxNum = 0;
        int temp = 0;
        for (TaskRouse s : rouses) {
            maxNum += s.getWeight();
           // System.out.println(s.getWeight()+":"+s.getSdkKey());
        }
        int random = RandomUtils.nextInt(1, maxNum);
        for (TaskRouse s : rouses) {

            if (temp < random && random <= (s.getWeight()+temp)) {
                //System.out.print("中了"); System.out.println(temp+"__"+random+"__"+(s.getWeight()+temp));
                return s;
            }
            temp = temp + s.getWeight();
        }
        System.out.println(random);
        return null;
    }


    /**
     * 取一个随机的数据源(不包括自营)
     *
     * @param headers
     * @param version
     * @return
     */
    public Optional<String> getRandomAdStringKey(RequestHeaders headers, int version, int l, List<String> filterSdkKey) {
        filterSdkKey.add("ABCD8888");
        TaskRouseExample example = new TaskRouseExample();
        example.createCriteria()
                .andBrandNotLike("%" + headers.getAppStore() + "%")
                .andEnableEqualTo(1)
                .andVersionLessThanOrEqualTo(version)
                .andSdkKeyNotEqualTo(ZY_DATA)
        .andSdkKeyNotIn(filterSdkKey);
        TaskRouse taskRouse = randomByWeight(rouseMapper.selectByExample(example));
        if(taskRouse!=null){
            return Optional.ofNullable(taskRouse.getSdkKey());
        }else {
            return Optional.empty();
        }
    }



    public static final String FILTER_KEY = "MEMBER_FILTER_SDKKEY:";

    /**
     * 获取用户的全部被限制的key
     *
     * @param memberId
     * @return
     */
    public List<String> filterSdkKey(String memberId) {
        Map<String, String> allKey = redisClient.hgetall(FILTER_KEY + memberId);
        long now = System.currentTimeMillis();
        List<String> strings = new ArrayList<>();
        allKey.forEach((k, v) -> {
            long waitTime = Long.parseLong(v);
            if (now > waitTime) {
                redisClient.hdel(FILTER_KEY + memberId, k);
            } else {
                strings.add(k);
            }
        });
        return strings;
    }

    public DownloadMemberRecord selectByRecordId(long recordId) {
        return recordMapper.selectByPrimaryKey(recordId);
    }

    public int push(long recordId, int category, RequestHeaders requsetHeader, String icon,String adId) {
        DownloadMemberRecord record = recordMapper.selectByPrimaryKey(recordId);
        record.setAdId(adId);
        record.setPushTime(LocalDateTime.now());
        record.setModifyTime(LocalDateTime.now());
        record.setStatus(DownStatus.SUCCESS.getIndex());
        record.setCategory(category);
        //兼容旧版
        if (record.getRewardType() == null) {
            record.setRewardType(1);
        }
        this.add(record.getMemberId(), record.getType());
        if (record.getRewardType().equals(RewardTypeUscan.Cash.getIndex())) {
            //金钱
            tradeService.addMoney(record.getMemberId(), record.getMoney(),
                    "恭喜完成任务", "完成每日必赚获得" + new BigDecimal(record.getMoney()).divide(new BigDecimal(100),
                            2, BigDecimal.ROUND_DOWN) + "元", "",
                    requsetHeader, JSON.toJSONString(record), new MoneyCategory(Whether.YES, TaskCategory.CSJ_ZXR));
            noticeService.addNoticeAndPush("恭喜完成任务", "完成每日必赚获得" + new BigDecimal(record.getMoney()).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN) + "元", record.getMemberId(), requsetHeader);
        } else if (record.getRewardType().equals(RewardTypeUscan.Point.getIndex())) {
            //金币
            pointService.addPointBySdk(record.getMemberId(), record.getMoney(),
                    TaskCategory.CSJ_ZXR, "完成每日必赚获得" + record.getMoney() + "金币", requsetHeader);
            noticeService.addNoticeAndPush("恭喜完成任务", "完成每日必赚获得" + record.getMoney() + "金币", record.getMemberId(), requsetHeader);
        }
        if (record.getPkgName() != null && record.getType() == 1) {
            TaskRouse rouse = this.selectByKey(record.getSdkKey());
            if (rouse.getHasClick() > 0) {
                this.clickInit(record, icon);
            }
        }
        recordMapper.updateByPrimaryKeySelective(record);

        return 1;
    }


    /**
     * 加载签到数据
     *
     * @param record
     */
    public void clickInit(DownloadMemberRecord record, String icon) {
        //验证是否能做签到。
        PkgEarnInfo pkgEarnInfo = pkgEarnInfoMapper.selectByPkgName(record.getPkgName());
        if (pkgEarnInfo != null) {
            if (pkgEarnInfo.getOpenClick().equals(0)) {
                return;
            }
        }
        //根据包名唯一
        MemberClickRouseExample example = new MemberClickRouseExample();
        List<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(-1);
        example.createCriteria()
                .andStatusIn(integers)
                .andHasDeletedEqualTo(0)
                .andPkgNameEqualTo(record.getPkgName())
                .andMemberIdEqualTo(record.getMemberId());
        long count = clickRouseMapper.countByExample(example);
        //不存在才添加数据
        if (count == 0) {
            TaskRouse taskRouse = this.selectByKey(record.getSdkKey());
            MemberClickRouse clickRouse = new MemberClickRouse();
            clickRouse.setCreateTime(LocalDateTime.now());
            clickRouse.setModifyTime(LocalDateTime.now());
            clickRouse.setHasDeleted(Whether.NO.getDbIndex());
            clickRouse.setPkgName(record.getPkgName());
            clickRouse.setLastTime(LocalDateTime.now());
            clickRouse.setCount(0);
            List<String> list = new ArrayList<>();
            clickRouse.setClickJson(JSON.toJSONString(list));
            clickRouse.setStatus(1);
            clickRouse.setMemberId(record.getMemberId());
            clickRouse.setAppName(record.getAppName());
            clickRouse.setIcon(icon);
            //签到体验时间
            clickRouse.setWaitTime(taskRouse.getRouseTime());
            clickRouse.setRouseId(taskRouse.getId());
            clickRouseMapper.insertSelective(clickRouse);
        }
    }

    public int upload(DownloadMemberRecord record, String appName, String pkgName) {
        if (!"cc.gara.fish.jj_fish".equals(pkgName)) {
            record.setAppName(appName);
            record.setPkgName(pkgName);
            downloadPkgDetailMapper.updateByAppName(appName, pkgName);
        }
        return recordMapper.updateByPrimaryKeySelective(record);
    }

    @Autowired
    private DictService dictService;
    @Autowired
    private RedisClient redisClient;


    /**
     * 判断是否超出了上限
     *
     * @param memberId
     * @param type
     * @return
     */
    public boolean checkPush(String memberId, DownCategory type) {
        if (type == null) {
            return true;
        }
        int i = 0;
        boolean on = redisClient.hexists(getKey(type.getIndex()), memberId);
        if (!on) {
            redisClient.hset(getKey(type.getIndex()), memberId, "0");
            //过期时间修改注释
            //redisClient.expire(getKey(type.getIndex()), 86400);
        } else {
            String str = redisClient.hget(getKey(type.getIndex()), memberId);
            i = Integer.parseInt(str);
        }
        if (type.equals(DownCategory.DOWN_LOAD)) {
            //下载型
            return i >= dictService.selectIntByKeyName("csj_down_success_count");
        } else {
            //浏览型
            return i >= dictService.selectIntByKeyName("csj__look_success_count");
        }

    }

    /**
     * 获取总剩余次数
     *
     * @param memberId
     * @return
     */
    public int getCount(String memberId) {
        //int hourMax=dictService.selectIntByKeyName("csj_max_hour_count");
        int allCount = dictService.selectIntByKeyName("csj_down_success_count") + dictService.selectIntByKeyName("csj__look_success_count");
        int downCount = this.getTypeCount(memberId, DownCategory.DOWN_LOAD);
        int lookCount = this.getTypeCount(memberId, DownCategory.LOOK);
        allCount = allCount - (downCount + lookCount);
        return allCount;
    }


    /**
     * 获取已用次数
     *
     * @param memberId
     * @param category
     * @return
     */
    public int getTypeCount(String memberId, DownCategory category) {
        String down = redisClient.hget(getKey(category.getIndex()), memberId);
        if (down == null) {
            return 0;
        } else {
            return Integer.parseInt(down);
        }
    }

    public static final String CSJ_RECORD_COUNT = "CSJ_RECORD_COUNT:";


    /**
     * app下载结束调用
     *
     * @param record
     * @return
     */
    public int downEnd(DownloadMemberRecord record) {
        record.setEndTime(LocalDateTime.now());
        recordMapper.updateByPrimaryKeySelective(record);
        return 1;
    }

    /**
     * 随机领取 浏览 或 下载
     *
     * @return
     */
    public int randomPullV2() {
        return RandomUtils.nextInt(0, 2);

    }

    /**
     * 随机领取 浏览 或 下载
     *
     * @param memberId
     * @return
     */
    public int randomPull(String memberId) {
        int randomInt = RandomUtils.nextInt(0, 2);
        DownCategory category = DownCategory.getByIndex(randomInt);
        if (category == null) {
            return -1;
        }
        boolean i = this.checkPush(memberId, DownCategory.getByIndex(randomInt));
        if (i) {
            if (category.equals(DownCategory.DOWN_LOAD)) {
                if (this.checkPush(memberId, DownCategory.LOOK)) {
                    return -1;
                } else {
                    return 0;
                }
            } else {
                if (this.checkPush(memberId, DownCategory.DOWN_LOAD)) {
                    return -1;
                } else {
                    return 1;
                }
            }
        } else {
            return randomInt;
        }
    }

    /**
     * 放弃任务
     *
     * @param record
     * @return
     */
    public int fail(DownloadMemberRecord record) {
        record.setStatus(DownStatus.RELSE.getIndex());
        record.setReleaseTime(LocalDateTime.now());
        return recordMapper.updateByPrimaryKeySelective(record);
    }

    public int getByStatus(Long id, int status, String sdkKey) {
        return recordMapper.getByStatus(id, status, sdkKey);
    }

    public static final String CJS_EXPIRE_MEMBER = "CSJ_EXPIRE_MEMBER:";

    /**
     * 增加每日次数
     *
     * @param memberId
     * @param type
     */
    public void add(String memberId, int type) {
        //领取次数+1
        redisClient.hincrby(getKey(type), memberId, 1L);
        long o = redisClient.hincrby(getHourKey(), memberId, 1L);
        //过期时间修改注释
        //redisClient.expire(getHourKey(), 86400);
        //过期时间修改注释
        //redisClient.expire(getKey(type), 86400);
        if (o >= dictService.selectIntByKeyName("csj_max_hour_count")) {
            redisClient.setex(getExpreKey(memberId), 3600, memberId);
        }
    }

    public String getKey(Integer type) {
        LocalDate date = LocalDate.now();
        return CSJ_RECORD_COUNT + date.format(DateTimeFormatter.ISO_DATE) + ":" + type;
    }

    public String getHourKey() {
        LocalDateTime date = LocalDateTime.now();
        return CSJ_RECORD_COUNT + date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH"));
    }


    /**
     * 获取超时key
     *
     * @param memberId
     * @return
     */
    public String getExpreKey(String memberId) {
        return CJS_EXPIRE_MEMBER + memberId;
    }

    public static final String INFO_KEY = "TaskRouse_VO";


    /**
     * 查询数据源
     *
     * @param key
     * @return
     */
    public TaskRouse selectByKey(String key) {
        if (TextUtil.isEmpty(key)) {
            return null;
        }
        TaskRouse rouse;
        Optional<String> str = Optional.ofNullable(redisClient.hget(INFO_KEY, key));
        if (str.isPresent()) {
            rouse = JSON.parseObject(str.get(), TaskRouse.class);
        } else {
            rouse = rouseMapper.selectByKey(key);
            redisClient.hset(INFO_KEY, key, JSON.toJSONString(rouse));
        }
        return rouse;

    }

    /**
     * 查询有没有做过包名应用名称
     *
     * @param appName
     * @param memberId
     * @param pkgName
     * @return
     */
    public DownloadMemberRecord selectByAppNameAndMemberId(String appName, String memberId, String pkgName) {
        if (TextUtil.isEmpty(pkgName)) {
            return recordMapper.selectByAppNameAndMemberId(appName, memberId, null, null, null);
        } else {
            return recordMapper.selectByAppNameAndMemberId(null, memberId, pkgName, null, null);
        }
    }

    /**
     * 查询今天有没有做过包名应用名称
     *
     * @param appName
     * @param memberId
     * @param pkgName
     * @return
     */
    public DownloadMemberRecord selectByAppNameAndMemberIdToday(String appName, String memberId, String pkgName) {
        LocalDate date = LocalDate.now();
        LocalDateTime star = LocalDateTime.of(date, LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(date, LocalTime.MAX);
        if (TextUtil.isEmpty(pkgName)) {
            return recordMapper.selectByAppNameAndMemberId(appName, memberId, null, star, end);
        } else {
            return recordMapper.selectByAppNameAndMemberId(null, memberId, pkgName, star, end);
        }
    }

    /**
     * 填充任务参数
     *
     * @param appName
     * @param memberId
     * @param record
     * @param pkgName
     * @return
     */
    public DownloadMemberRecord initRecord(String appName, String memberId,
                                           DownloadMemberRecord record, String pkgName) {
        DownloadMemberRecord roc = this.selectByAppNameAndMemberId(appName, memberId, pkgName);
        TaskRouse taskRouse = this.selectByKey(record.getSdkKey());
        if (roc == null) {
            //首次
            if (record.getType().equals(DownCategory.DOWN_LOAD.getIndex())) {
                //下载型
                record.setCategory(DownReword.DOWN_FIRST.getIndex());
            } else {
                //浏览型
                record.setCategory(DownReword.NONE_IN.getIndex());
            }
        } else {
            //非首次
            if (record.getType().equals(DownCategory.DOWN_LOAD.getIndex())) {
                //下载型
                record.setCategory(DownReword.DOWN_UN_FIRST.getIndex());

            } else {
                //浏览型
                record.setCategory(DownReword.NONE_IN.getIndex());
            }
        }
        int money = this.getDownMoneyByRouse(memberId, taskRouse, record.getCategory());
        record.setMoney(money);
        record.setAppName(appName);
        record.setPkgName(pkgName);
        recordMapper.updateByPrimaryKeySelective(record);
        return record;
    }

    /**
     * 获取可签到列表<条件>小于7天并且连续签到不能断</> 并且检测是否连续签到
     *
     * @param memberId
     * @return
     */
    public List<MemberClickRouse> getClickList(String memberId) {
        TaskRouseExample example1 = new TaskRouseExample();
        List<TaskRouse> rouses3 = rouseMapper.selectByExample(example1);
        List<Long> longs = new ArrayList<>();
        rouses3.forEach(s -> {
            if (s.getHasClick() == 1) {
                longs.add(s.getId());
            }
        });
        if (longs.size() == 0) {
            return null;
        }
        //查询连续签到7天以下的可签到数据
        MemberClickRouseExample example = new MemberClickRouseExample();
        example.createCriteria()
                .andStatusEqualTo(1)
                .andHasDeletedEqualTo(0)
                .andMemberIdEqualTo(memberId)
                .andRouseIdIn(longs);
        return clickRouseMapper.selectByExample(example);
    }

    public MemberClickRouse findClickByClickId(long clickId) {
        return clickRouseMapper.selectByPrimaryKey(clickId);
    }

    /**
     * 加载今日签到和明日签到
     *
     * @param s           签到数据详情
     * @param days        当前是下载起第几天
     * @param rouseClicks 签到配置
     */
    public boolean clickInit(MemberClickRouse s, int days, List<TaskRouseClick> rouseClicks, LocalDate now) {
        for (TaskRouseClick next : rouseClicks) {
            if (next.getDayCount() >= days && next.getRouseId().equals(s.getRouseId())) {
                //今天签到的
                if (next.getDayCount() == days) {
                    //   今天签过就到明天
                    if (this.checkClickByMemberId(s.getMemberId(), s.getId(), now)) {
                        //明天可签就返回 不然删除
                        for (TaskRouseClick vo : rouseClicks) {
                            if (vo.getDayCount() >= (days + 1) && vo.getRouseId().equals(s.getRouseId())) {
                                s.setStatus(2);
                                if (vo.getRewardType().equals(RewardTypeUscan.Cash.getIndex())) {
                                    s.setWorth(vo.getDayMoney());
                                } else {
                                    s.setWorth(vo.getDayPoint());
                                }
                                s.setClickDay(s.getCreateTime().plusDays(vo.getDayCount()).getDayOfMonth());
                                return true;
                            }
                        }
                        return false;
                    }
                    s.setClickDay(0);
                } else {
//                    //明天签到的-
//                    if (next.getDayCount() == days + 1) {
//                        s.setStatus(2);
//                        s.setClickTime(s.getCreateTime().plusDays(next.getDayCount()).toLocalDate());
//                    } else {
//                        //其他签到的 隐藏
//                        return false;
//                    }
//                    s.setClickDay(s.getCreateTime().plusDays(next.getDayCount()).getDayOfMonth());
                    s.setStatus(2);
                    s.setClickDay(s.getCreateTime().plusDays(next.getDayCount()).getDayOfMonth());

                }
                if (next.getRewardType().equals(RewardTypeUscan.Cash.getIndex())) {
                    s.setWorth(next.getDayMoney());
                } else {
                    s.setWorth(next.getDayPoint());
                }
                return true;
            }
        }
        return false;
    }


    /**
     * 修改签到数据 并且奖励
     *
     * @param now
     * @param vo
     * @param strings
     */
    public void clickAdd(String now, MemberClickRouse vo, List<String> strings, RequestHeaders header, TaskRouseClick po, int days, int star) {
        MemberClidkRouseRecord record = new MemberClidkRouseRecord();
        TaskRouse rouse = rouseMapper.selectByPrimaryKey(vo.getRouseId());
        strings.add(now);
        vo.setCount(vo.getCount() + 1);
        vo.setLastTime(LocalDateTime.now());
        vo.setClickJson(JSON.toJSONString(strings));
        record.setUa(header.getUa());
        record.setImei(header.getImei());
        record.setIpAddress(header.getIpAddr());
        record.setAppStore(header.getAppStore());
        record.setRewardType(rouse.getRewardType());
        record.setDays(star);
        clickRouseMapper.updateByPrimaryKeySelective(vo);
        int money = this.getClickMoneyByRouseClick(po);
        if (po.getRewardType().equals(RewardTypeUscan.Cash.getIndex())) {
            //金钱
            tradeService.addMoney(vo.getMemberId(), money, "恭喜完成任务",
                    "完成每日必赚签到" + new BigDecimal(money).divide(new BigDecimal(100),
                            2, BigDecimal.ROUND_DOWN) + "元", "",
                    header, "", new MoneyCategory(Whether.YES, TaskCategory.EARN_CLICK));
            uMengPushComponent.sendNoRead("恭喜完成任务", "完成每日必赚获得" + new BigDecimal(money).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN) + "元", vo.getMemberId());
            noticeService.addNotice("恭喜完成任务", "完成每日必赚获得" + new BigDecimal(money).divide(new BigDecimal(100), 2, BigDecimal.ROUND_DOWN) + "元", vo.getMemberId(), header);
            record.setWorth(money);
        } else {
            //金币
            pointService.addPointBySdk(vo.getMemberId(), money, TaskCategory.EARN_CLICK,
                    "完成每日必赚签到" + money + "金币", header);
            uMengPushComponent.sendNoRead("恭喜完成任务", "完成每日必赚签到" + money + "金币", vo.getMemberId());
            noticeService.addNotice("恭喜完成任务", "完成每日必赚签到" + money + "金币", vo.getMemberId(), header);
            record.setWorth(money);
        }
        record.setCreateTime(LocalDateTime.now());
        record.setMemberId(vo.getMemberId());
        record.setClickTime(LocalDate.now());
        record.setClcikRouseId(vo.getId());
        record.setRouseId(rouse.getId().intValue());
        record.setDayCount(po.getDayCount());
        clidkRouseRecordMapper.insertSelective(record);
    }


    public String getClickMoneyByRouseClickStr(ClickStrategyDetail po) {
        if (po.getRewardType() > 0) {
            return po.getDayMoney() + "分";
        } else {
            return po.getDayPoint() + "金币";
        }
    }

    private int getClickMoneyByRouseClick(TaskRouseClick po) {
        if (po.getRewardType() > 0) {
            return po.getDayMoney();
        } else {
            return po.getDayPoint();
        }
    }

    public String getClickMoneyByRouseClickStr(TaskRouseClick po) {
        if (po.getRewardType() > 0) {
            return po.getDayMoney() + "分";
        } else {
            return po.getDayPoint() + "金币";
        }
    }

    /**
     * 获取用户首次下载任务最终衰减的值
     *
     * @param memberId
     * @param rouse
     * @return
     */
    private int getDownMoneyByRouse(String memberId, TaskRouse rouse, int category) {
        int count = this.getDownCount(memberId, category, rouse.getSdkKey());
        int money;
        int minMoney;
        int reductionMoney;
        if (rouse.getRewardType().equals(RewardTypeUscan.Cash.getIndex())) {
            if (category == 1) {
                money = rouse.getFirstReward();
                minMoney = rouse.getFirstRewardMin();
                reductionMoney = rouse.getFirstRewardReduction();
            } else if (category == 2) {
                money = rouse.getFirstReward();
                minMoney = rouse.getRouseRewardMin();
                reductionMoney = rouse.getRouseRewardReduction();
            } else {
                money = rouse.getLookReward();
                minMoney = rouse.getLookRewardMin();
                reductionMoney = rouse.getLookRewardReduction();
            }
        } else if (rouse.getRewardType().equals(RewardTypeUscan.Point.getIndex())) {
            if (category == 1) {
                money = rouse.getFirstRewardPoint();
                minMoney = rouse.getFirstRewardPointMin();
                reductionMoney = rouse.getFirstRewardPointReduction();
            } else if (category == 2) {
                money = rouse.getRouseRewardPoint();
                minMoney = rouse.getRouseRewardPointMin();
                reductionMoney = rouse.getRouseRewardPointReduction();
            } else {
                money = rouse.getLookRewardPoint();
                minMoney = rouse.getLookRewardPointMin();
                reductionMoney = rouse.getLookRewardPointReduction();
            }
        } else {
            return 0;
        }
        int reductionMoneyAll = (reductionMoney * count);
        if (minMoney > money - reductionMoneyAll) {
            money = minMoney;
        } else {
            money = money - reductionMoneyAll;
        }
        return money;
    }

    /**
     * 获取用户完成的次数 一个自然日算完成一次
     *
     * @param memberId
     * @param category
     * @param sdkKey
     * @return
     */
    private int getDownCount(String memberId, int category, String sdkKey) {
        Optional<String> str = redisClient.Optionalhget(MEMBER_SDK_CATEGORY_COUNT, memberId + ":" + category + ":" + sdkKey);
        int count;
        if (str.isPresent()) {
            count = Integer.parseInt(str.get());
        } else {
            //未初始化的 初始化一下。
            count = recordMapper.selectCountByMemberIdAndCategory(memberId, category, sdkKey);
            redisClient.hset(MEMBER_SDK_CATEGORY_COUNT, memberId + ":" + category + ":" + sdkKey, String.valueOf(count));
        }
        return count;
    }

    private static final String MEMBER_SDK_CATEGORY_COUNT = "MEMBER_SDK_CATEGORY_COUNT";

    /**
     * 验证用户哪天有没有签到过
     *
     * @param memberId
     * @return
     */
    public boolean checkClickByMemberId(String memberId, long rouseId, LocalDate date) {
        MemberClidkRouseRecordExample example = new MemberClidkRouseRecordExample();
        example.createCriteria().andClcikRouseIdEqualTo(rouseId)
                .andMemberIdEqualTo(memberId)
                .andClickTimeEqualTo(date);
        return clidkRouseRecordMapper.countByExample(example) > 0;
    }


    /**
     * 与天卓珊瑚订单号绑定
     *
     * @param record
     * @return
     */
    public int bindOrderIdByRecordId(DownloadMemberRecord record) {
        record.setModifyTime(LocalDateTime.now());
        return recordMapper.updateByPrimaryKeySelective(record);
    }

    public void pushByOrderId(String orderId) {
        DownloadMemberRecord record = recordMapper.selectByOrderId(orderId);
        if (record != null) {
            this.downEnd(record);
        }
    }


    /**
     * 修改KEY
     *
     * @param record
     */
    public void updateKey(DownloadMemberRecord record) {
        record.setModifyTime(LocalDateTime.now());
        recordMapper.updateByPrimaryKeySelective(record);
    }

    /**
     * 统计成功数
     *
     * @param star   开始时间
     * @param end    结束时间
     * @param sdkKey 数据源标识
     * @param status 状态码
     * @return
     */
    public long selectSuccessByTime(LocalDateTime star, LocalDateTime end, String sdkKey, Integer status) {
        DownloadMemberRecordExample example = new DownloadMemberRecordExample();
        example.createCriteria().andSdkKeyEqualTo(sdkKey).andCreateTimeBetween(star, end).andStatusEqualTo(status);
        return recordMapper.countByExample(example);
    }

    public static final String DAY_EARNS_COUNT = "DAY_EARNS_COUNT:";
    public static final String MAX_EARNS_COUNT = "MAX_EARNS_COUNT";

    public static String getMaxKey(String appStore) {
        return MAX_EARNS_COUNT + ":" + appStore;
    }

    /**
     * 验证用户还能不能做任务
     *
     * @param requestHeaders
     * @return
     */
    public boolean checkPushV2(RequestHeaders requestHeaders, int count, String appStore) {
        if (!redisClient.hexists(AppEarnRouseSortService.getKey(appStore), "1")) {
            appStore = "all";
        }
        //    Optional<String> imei = redisSdkClient.Optionalhget(getKeyV2(), requestHeaders.getImei());

        Optional<String> str = redisClient.Optionalhget(getKeyV2(), requestHeaders.getUserid());
        //用户完成数
        Integer memberCount = str.map(Integer::parseInt).orElse(0);
        //设备完成数
        //       Integer imeiCount = imei.map(Integer::parseInt).orElse(0);

        Optional<String> maxStr = Optional.ofNullable(redisClient.get(getMaxKey(appStore)));
        Integer maxCount = maxStr.map(Integer::parseInt).orElse(0);
//        //验证设备完成数
//       boolean check;
//        if (count > 0) {
//            check =imeiCount >= count || (imeiCount >= maxCount);
//        } else {
//            check =(imeiCount >= maxCount);
//        }
//        if(check){
//            return true;
//        }
        if (count > 0) {
            return memberCount >= count || (memberCount >= maxCount);
        } else {
            return (memberCount >= maxCount);
        }

    }

    /**
     * 获取用户今天还剩余几次任务
     *
     * @param memberId
     * @return
     */
    public Integer getCountV2(String memberId, String appStore) {
        if (!redisClient.hexists(AppEarnRouseSortService.getKey(appStore), "1")) {
            appStore = "all";
        }
        Optional<String> str = redisClient.Optionalhget(getKeyV2(), memberId);
        Integer memberCount = str.map(Integer::parseInt).orElse(0);
        Optional<String> maxStr = Optional.ofNullable(redisClient.get(getMaxKey(appStore)));
        Integer maxCount = maxStr.map(Integer::parseInt).orElse(0);
        return Math.max(maxCount - memberCount, 0);
    }

    /**
     * 获取今天这次是第几次
     *
     * @param memberId
     * @return
     */
    public int getTodayCountV2(String memberId) {
        Optional<String> str = redisClient.Optionalhget(getKeyV2(), memberId);
        Integer memberCount = str.map(Integer::parseInt).orElse(0);
        return memberCount + 1;

    }

    /**
     * 用户今天完成次数+1
     *
     * @param headers
     * @return
     */
    public int addV2(RequestHeaders headers, String sdkKey) {
        //过期时间修改注释
        //redisClient.expire(getKeyV2(), 86000);
        //过期时间修改注释
        //redisClient.expire(getSdkKey(sdkKey), 86000);
        redisClient.hincrby(getSdkKey(sdkKey), headers.getUserid(), 1L);
        redisSdkClient.hincrby(getSdkKey(sdkKey), headers.getImei(), 1L);
        if (sdkKey.equals(ZY_DATA)) {
            return 1;
        }
        if(redisSdkClient.hexists(getAllSdkKey(), headers.getImei()+":"+sdkKey)){
            redisSdkClient.hincrby(getAllSdkKey(), headers.getImei()+":"+sdkKey, 1L);
        }else {
            redisSdkClient.hset(getAllSdkKey(), headers.getImei()+":"+sdkKey,
                    String.valueOf(recordMapper.selectSuccessCountByImei(headers.getImei(),sdkKey)));
        }

        redisSdkClient.hincrby(getKeyV2(), headers.getImei(), 1L);
        return redisClient.hincrby(getKeyV2(), headers.getUserid(), 1L).intValue();
    }

    /**
     * 获取今天这次是第几次
     *
     * @param requestHeaders
     * @return
     */
    public int getCountBySdkKey(RequestHeaders requestHeaders, String sdkKey) {

        Optional<String> str = redisClient.Optionalhget(getSdkKey(sdkKey), requestHeaders.getUserid());
        Integer memberCount = str.map(Integer::parseInt).orElse(0);
        Optional<String> imei = redisSdkClient.Optionalhget(getSdkKey(sdkKey), requestHeaders.getImei());
        Integer imeiCount = imei.map(Integer::parseInt).orElse(0);
        if (memberCount > imeiCount) {
            return memberCount;
        } else {
            return imeiCount;
        }

    }

    /**
     * 获取数据源用户每日完成次数的key
     *
     * @param sdkKey
     * @return
     */
    public static String getSdkKey(String sdkKey) {
        String date = LocalDate.now().format(DateTimeFormatter.ISO_DATE);
        return DAY_EARNS_COUNT + sdkKey + ":" + date;
    }

    /**
     * 获取数据源用户每日完成次数的key
     *
     * @param
     * @return
     */
    private String getAllSdkKey() {
        return "ALL"+DAY_EARNS_COUNT;
    }

    /**
     * 获取完成次数的key
     *
     * @return
     */
    private String getKeyV2() {
        String date = LocalDate.now().format(DateTimeFormatter.ISO_DATE);
        return DAY_EARNS_COUNT + date;
    }

    public static final String DAY_EARNS_ALL_COUNT = "DAY_EARNS_ALL_COUNT";

    private String getKeyTodaySuccessCount() {
        String date = LocalDate.now().format(DateTimeFormatter.ISO_DATE);
        return DAY_EARNS_ALL_COUNT + date;
    }


    /**
     * 今日总成功数+1
     *
     * @return
     */
    public void addSuccessCount() {
        redisClient.incrBy(getKeyTodaySuccessCount(), 1L);
        //过期时间修改注释
        //redisClient.expire(getKeyTodaySuccessCount(), 86400);
    }

    /**
     * 单任务价值
     *
     * @param record
     */
    public void addDownCount(DownloadMemberRecord record) {
        if (record.getCategory() == null) {
            record.setCategory(1);
        }
        LocalDateTime star = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime end = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
        this.getDownCount(record.getMemberId(), record.getCategory(), record.getSdkKey());
        DownloadMemberRecordExample example = new DownloadMemberRecordExample();
        example.createCriteria()
                .andMemberIdEqualTo(record.getMemberId())
                .andStatusEqualTo(1)
                .andSdkKeyEqualTo(record.getSdkKey())
                .andCreateTimeBetween(star, end)
                .andCategoryEqualTo(record.getCategory());
        if (recordMapper.countByExample(example) == 0) {
            redisClient.hincrby(MEMBER_SDK_CATEGORY_COUNT, record.getMemberId() + ":" + record.getCategory() + ":" + record.getSdkKey(), 1L);
        }
    }

    public int getSuccessByMemberId(String memberId) {
        return recordMapper.selectSuccessCount(memberId);
    }

    public void failBySys(DownloadMemberRecord record) {
        record.setStatus(DownStatus.SYS_RELSE.getIndex());
        record.setReleaseTime(LocalDateTime.now());
        recordMapper.updateByPrimaryKeySelective(record);
    }

    /**
     * 验证是否超过了每日必赚最大值
     *
     * @param rouse
     * @param headers
     * @return
     */
    public TaskRouse checkSdkMax(TaskRouse rouse, RequestHeaders headers, List<String> list) {
        LocalDateTime localDateTime = lbbMemberMapper.selectCreaTimeByMemberId(headers.getUserid());
        int maxCount;
        boolean isNewMember = localDateTime.toLocalDate().equals(LocalDate.now());
        if (isNewMember) {
            maxCount = rouse.getNewMaxDayCount();
        } else {
            maxCount = rouse.getMaxDayCount();
        }
        //取sdk最大次数。
        int allCount = this.getAllCountBySdkKey(headers, rouse.getSdkKey());
        //取sdk当日最大次数。
        int count = this.getCountBySdkKey(headers, rouse.getSdkKey());
        if ((count >= maxCount || maxCount == 0) || (allCount >= rouse.getMaxCount())) {
            list.remove(rouse.getSdkKey());
            for (String s : list) {
                allCount = this.getAllCountBySdkKey(headers, s);
                count = this.getCountBySdkKey(headers, s);
                rouse = this.selectByKey(s);
                if (isNewMember) {
                    maxCount = rouse.getNewMaxDayCount();
                } else {
                    maxCount = rouse.getMaxDayCount();
                }
                if (maxCount == 0) {
                    continue;
                }
                if (count < maxCount && allCount < rouse.getMaxCount()) {
                    return rouse;
                }
            }
            return null;
        } else {
            return rouse;
        }
    }

    public int getAllCountBySdkKey(RequestHeaders headers, String sdkKey) {
        Optional<String> imei = redisSdkClient.Optionalhget(getAllSdkKey(), headers.getImei()+":"+sdkKey);
        return imei.map(Integer::parseInt).orElse(0);
    }



    /**
     * 获取用户今日放弃数量
     *
     * @param requestHeaders
     * @return
     */
    public int getFailCount(RequestHeaders requestHeaders) {
        String str = redisClient.hget(getFailKey(), requestHeaders.getUserid());
        return Optional.ofNullable(str).map(Integer::parseInt).orElse(0);
    }

    /**
     * 获取放弃的KEY
     *
     * @return
     */
    public String getFailKey() {
        return "FAIL_COUNT:" + LocalDate.now().format(DateTimeFormatter.ISO_DATE);
    }

    /**
     * 放弃数量+1
     *
     * @param requestHeaders
     * @return
     */
    public long addFailCount(RequestHeaders requestHeaders) {
        return redisClient.hincrby(getFailKey(), requestHeaders.getUserid(), 1L);
    }

    /**
     * 打开APP时验证用户每日必赚总次数是否用完
     *
     * @param requestHeaders
     */
    public void checkHasRecord(RequestHeaders requestHeaders) {
        TaskRouseExample example = new TaskRouseExample();
        example.createCriteria().andEnableEqualTo(Whether.YES.getDbIndex()).andSdkKeyNotEqualTo(ZY_DATA);
        List<TaskRouse> strings = rouseMapper.selectByExample(example);
        int count = 0;
        for (TaskRouse s : strings) {
            int allCountBySdkKey = getAllCountBySdkKey(requestHeaders, s.getSdkKey());
            if (allCountBySdkKey >= s.getMaxCount()) {
                count++;
            }
        }
        if (count == strings.size()) {
            redisSdkClient.hset("EARN:LOCK:HASH", requestHeaders.getImei(), "1");
        } else {
            redisSdkClient.hdel("EARN:LOCK:HASH", requestHeaders.getImei());
        }
    }

    /**
     * 验证能不能显示每日必赚入口
     *
     * @param requestHeaders
     * @return
     */
    public boolean checkDoRecord(RequestHeaders requestHeaders) {
        return redisSdkClient.hexists("EARN:LOCK:HASH", requestHeaders.getImei());
    }

    /**
     * 清除这个用户 和设备号的全部已做次数为0
     *
     * @param memberId
     */
    public void cleanCount(String memberId) {
        List<TaskRouse> rouses = rouseMapper.selectByExample(null);
        LbbMember member = lbbMemberMapper.selectById(memberId);

        rouses.forEach(s -> {
            redisSdkClient.hdel(getSdkKey(s.getSdkKey()), member.getImei());
            redisClient.hdel(getSdkKey(s.getSdkKey()), memberId);
            redisSdkClient.hdel(getAllSdkKey(),member.getImei()+":"+s.getSdkKey());
        });


    }

    /**
     * 查询数据源
     * @param id
     * @return
     */
    public TaskRouse selectTaskRouse(Long id){
        return rouseMapper.selectByPrimaryKey(id);
    }

    /**
     * 修改每日必赚记录
     * @param record
     * @return
     */
    public DownloadMemberRecord updateRecord(DownloadMemberRecord record){
       recordMapper.updateByPrimaryKeySelective(record);
       return record;
    }
}
